package jdl.synchronization;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import jdl.databaseObjects.DbField;
import jdl.databaseObjects.DbType;
import jdl.databaseObjects.FieldCollection;
import jdl.databaseObjects.datatypes.postgreSql.PostgreSqlDbTypeFactory;
import jdl.databaseObjects.sqlite.datatypes.VarcharDbType;

public class PostgreSqlSynchronizer {
	private Connection connection;

	public PostgreSqlSynchronizer(Connection connection) {
		this.connection = connection;
	}

	public void synchronizeField(DbField field) throws SynchronizationException {
		String sql = "SELECT typname FROM pg_type WHERE oid = (SELECT atttypid FROM pg_attribute WHERE attrelid = (SELECT oid FROM pg_class WHERE relname = ?) and attname = ?)";
		try {
			PreparedStatement statement = connection.prepareStatement(sql);
			statement.setString(1, field.getFieldCollection().getTable()
					.getName());
			statement.setString(2, field.getName());
			ResultSet resultSet = statement.executeQuery();
			if (resultSet.next()) {
				String typeName = resultSet.getString("typname");
				field.changeDbType(PostgreSqlDbTypeFactory.fromString(typeName));
			} else {
				throw new DbObjectNotFoundException(String.format(
						"field %s not found.", field.getName()));
			}
		} catch (DbObjectNotFoundException e) {
			throw e;
		} catch (Exception e) {
			throw new SynchronizationException(e);
		}
	}

	public void synchronizeFieldCollection(FieldCollection fieldCollection)
			throws SynchronizationException {
		String sql = "SELECT a.attname, t.typname, a.atttypmod FROM pg_type t, pg_attribute a WHERE t.oid = a.atttypid and a.attrelid = (SELECT oid FROM pg_class WHERE relname = ?) and a.attname not in ('tableoid', 'ctid', 'xmin', 'xmax', 'cmin', 'cmax')";
		try {
			PreparedStatement statement = connection.prepareStatement(sql);
			statement.setString(1, fieldCollection.getTable().getName());
			ResultSet resultSet = statement.executeQuery();
			while (resultSet.next()) {
				String fieldName = resultSet.getString("attname");
				String typeName = resultSet.getString("typname");
				DbType type = null;
				if (typeName.compareToIgnoreCase("varchar") == 0) {
					int size = resultSet.getInt("atttypmod");
					type = new VarcharDbType(size - 4);
				} else {
					type = PostgreSqlDbTypeFactory.fromString(typeName);
				}
				DbField field = new DbField(fieldName, type);
				fieldCollection.add(field);
			}
		} catch (Exception e) {
			throw new SynchronizationException(e);
		}
	}
}
